/*-----------------------------------------------------------------------------
	The contents of this file are subject to the Mozilla Public License
	Version 1.1 (the "License"); you may not use this file except in
	compliance with the License.You may obtain a copy of the License at
	http://www.mozilla.org/MPL/MPL-1.1.html
	
	Software distributed under the License is distributed on an "AS IS"
	basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
	License for the specific language governing rights and limitations
	under the License.
	
	The Original Code is Fever Framework code.
	
	The Initial Developer of the Original Code is Romain Ecarnot.
	Portions created by Initial Developer are Copyright (C) 2006
	the Initial Developer. All Rights Reserved.
	
	Contributor(s):
	
	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.
-----------------------------------------------------------------------------*/

import com.bourre.commands.Delegate;
import com.bourre.core.HashCodeFactory;
import com.bourre.data.collections.Map;
import com.bourre.data.iterator.Iterator;
import com.bourre.events.EventBroadcaster;
import com.bourre.events.EventType;

import fever.app.menu.FvContextMenuEvent;
import fever.app.menu.FvContextMenuHelper;
import fever.app.menu.FvContextMenuItem;
import fever.utils.Stringifier;

/**
 * Context menu.
 * 
 * <p>You can use old style using {@code MovieClip.menu} affectation, but Fever 
 * ContextMenu API adds some interesting features like : 
 * <ul>
 *   <li>Event support</li>
 *   <li>Menu / Item retreiving using {@link fever.app.menu.FvContextMenuHelper} 
 *   class</li>
 * <ul>
 * 
 * <p>Example
 * {@code
 *   public function test() : Void
 *   {
 *   	//build a new item
 *   	var item : FvContextMenuItem = new FvContextMenuItem ("Search on Google");
 *   	item.url = "http://www.google.com";
 *   	item.addEventListener ( FvContextMenuEvent.onContextItemEVENT, this, _onItemClick );
 *   	
 *   	//build a new FContextMenu
 *   	var contextMenu : FvContextMenu = new FvContextMenu ();
 *   	
 *   	//hides default flash items
 *   	contextMenu.hideBuiltInItems ();
 *   	
 *   	//add my item to menu
 *   	contextMenu.push (item );
 *   	
 *   	//association with main application context menu
 *   	Fever.application.contextMenu = contextMenu;
 *   	
 *   	//association with basic MovieClip
 *   	myMovieClip.menu = contextMenu.menu;
 *   }
 *   
 *   private function _onItemClick ( event : ContextMenuEvent ) : Void
 *   {
 *   	FeverDebug.DEBUG ("select item " + event.getTarget().caption + " on " + event.mouseTarget );
 *   	getURL ( event.getTarget().url, "_blank" );
 *   }
 * }
 * 
 * @see fever.app.menu.FvContextMenuHelper
 * @see fever.app.menu.FvContextMenuItem
 * 
 * @author Romain Ecarnot
 */
class fever.app.menu.FvContextMenu extends EventBroadcaster
{
	//-------------------------------------------------------------------------
	// Events definition
	//-------------------------------------------------------------------------
	
	/** Dispatched whe user right-click on application. */
	public static var onContextMenuEVENT : EventType = FvContextMenuEvent.onContextMenuEVENT;
	
	
	//-------------------------------------------------------------------------
	// Private properties
	//-------------------------------------------------------------------------
	
	private var _items : Map;
	private var _menu : ContextMenu;
		
	
	//-------------------------------------------------------------------------
	// Public Properties
	//-------------------------------------------------------------------------
	
	/** Returns real ContextMenu instance. **/
	public function get menu() : ContextMenu { return _buildContextMenu(); }
	
	
	//-------------------------------------------------------------------------
	// Public API
	//-------------------------------------------------------------------------
	
	/**
	 * Constructor.
	 */
	public function FvContextMenu( menuName : String )
	{
		super( this );
		
		if( !menuName ) menuName = '__contextmenu__' + HashCodeFactory.getKey(this);
		FvContextMenuHelper.register( this, menuName );
		
		_menu = new ContextMenu( Delegate.create(this, _select) );
		_items = new Map();
		
		hideBuiltInItems();
	}
	
	/**
	 * Adds passed-in {@code item} in context menu.
	 * 
	 * <p>Items with same id can't be added into the menu.
	 * 
	 * @param item {@link fever.app.menu.FvContextMenuItem} item
	 * @param id (optional) item id (useful to retreive item somewhere in 
	 * application.
	 * 
	 * @return {@code String} added item's id
	 */
	public function push( item : FvContextMenuItem, id : String ) : String
	{
		if( !id ) 
		{
			id = ( item.id ) ? item.id : ( '__citem__' + HashCodeFactory.getKey( item ) );
		}
		
		if( !_items.containsKey( id ) )
		{
			item.contextMenuOwner = this;
			_items.put( id, item );
		}
		return id;
	}
	
	/**
	 * Removes passed-in {@code item} from context menu.
	 * 
	 * @param id item's id to remove
	 */
	public function remove( id : String ) : Void
	{
		_items.remove( id );
	}
	
	/**
	 * Returns {@code FvContextMenuItem} using his registration id.
	 * 
	 * @param id @param id item's id to retreive
	 */
	public function getItem( id : String ) : FvContextMenuItem
	{
		return 	_items.get( id );
	}
	
	/**
	 * Hides (or not) builtin menu item.
	 * 
	 * @param visible (optional) {@code true} to hide menu, {@code false} to show it, 
	 * default is {@code true}
	 */
	public function hideBuiltInItems( visible : Boolean ) : Void
	{
		if( visible == undefined || visible == null) visible = true;
		if( visible )
		{
			_menu.hideBuiltInItems();
		}
		else
		{
			for( var item : String in _menu.builtInItems )
			{
    			_menu.builtInItems[item].visible = true;
			}		
		}
	}
	
	/**
	 * Returns {@code true} if passed-in item {@code id} is registred in 
	 * current context menu, otherwise {@code false}.
	 */
	public function isRegistred( id : String ) : Boolean
	{
		return 	_items.containsKey( id );
	}
	
	/**
	 * Removes all context menu items.
	 */
	public function release() : Void
	{
		removeAllListeners();
		
		var it : Iterator = _items.getKeysIterator();
		while( it.hasNext() )
		{
			var item : FvContextMenuItem = it.next();
			item.removeEventListener();	
		}
		_items.clear();
	}
	
	/**
	 * Returns string representation.
	 */
	public function toString() : String
	{
		return Stringifier.parse( this );
	}
	
	
	//-------------------------------------------------------------------------
	// Private implementation
	//-------------------------------------------------------------------------
	
	/**
	 * Returns correct Adobe {@code ContextMenu} instance for 
	 * visual instance affectation.
	 * 
	 * @return {@code ContextMenu} instance
	 */
	private function _buildContextMenu() : ContextMenu
	{
		var iterator : Iterator = _items.getValuesIterator();
		_menu.customItems = new Array();
		
		while( iterator.hasNext() )
		{
			_menu.customItems.push( iterator.next() );
		}
		return _menu;
	}
	
	/**
	 * Called when a user invokes the Flash Player context menu, but before the 
	 * menu is actually displayed.
	 * 
	 * <p>Dispatch {@link fever.app.menu.FvContextMenuEvent#MENU_SELECT} event.
	 */
	private function _select( obj : Object, menu : ContextMenu  ) : Void
	{
		var event : FvContextMenuEvent = new FvContextMenuEvent( FvContextMenuEvent.onContextMenuEVENT, this, null );
		event.mouseTarget = obj;
		broadcastEvent( event );
	}
}